//
//  WBStatusListViewModel.swift
//  shanshanlol微博
//
//  Created by 叶竞泽 on 2017/1/16.
//  Copyright © 2017年 JingZe. All rights reserved.
//

import Foundation
import SDWebImage

/// 微博数据列表视图模型
/// 父类的选择:如果类需要kvc或者字典转模型,类就需要继承自nsobject.如果类只是包装一些代码逻辑,可以不用任何父类
/// 1.字典转模型 2.处理上拉下拉

/// 上拉刷新最大尝试次数
private let maxPullUpTryTimes = 3

class WBStatusListViewModel {
    
    /// 微博模型数组
    lazy var statusList = [WBStatusViewModel]()
    
    /// 上拉刷新错误次数
    private var pullUpErrorTimes = 0
    
    /// 加载微博列表
    /// - Parameter pullUp: 是否是上拉刷新的标记
    /// - Parameter completion: 回调
    /// - Parameter hasMorePullUp: 是否有更多的上拉刷新
    func loadStatus(pullUp: Bool, completion: @escaping (_ isSuccess: Bool, _ shouldRefresh: Bool) -> ()) {
        
        /// 判断是否是上拉刷新,同时检查刷新错误
        if pullUp && pullUpErrorTimes > maxPullUpTryTimes {
            completion(true, false)
            return
        }
        
        /// 上拉刷新的ID
        let since_id = pullUp ? 0 : (statusList.first?.status.id ?? 0)
        
        /// 下拉刷新的ID
        let max_id = !pullUp ? 0 : (statusList.last?.status.id ?? 0)
        
        // 让数据访问层加载数据
        WBStatusDAL.loadStatus(since_id: since_id, max_id: max_id) { (list, isSuccess) in
            
            // 1.判断网络请求是否成功
            if !isSuccess {
                // 直接回调返回
                completion(false, false)
                return
            }
            
            // 2.字典转模型(第三方框架支持嵌套的字典转模型),模型 -> 视图模型
            var array = [WBStatusViewModel]()
            
            for dict in list ?? [] {
                
                // 1).创建微博模型
                guard let model = SSWBStatus.yy_model(with: dict) else {
                    continue
                }
                // 2).将model添加到数组
                array.append(WBStatusViewModel.init(model: model))
            }
            
            // 3.拼接数据
            // 下拉刷新,新的微博拼接在数组前面
            if !pullUp {
                self.statusList = array + self.statusList
                print("下拉刷新,刷新到\(array.count)条数据")
            } else {
                // 上拉刷新,新的微博拼接在数组后面
                self.statusList += array
                print("上拉刷新,加载了\(array.count)条数据")
            }
            
            // 4.判断上拉刷新的数据量
            if pullUp && array.count == 0 {
                self.pullUpErrorTimes += 1
                completion(isSuccess, false)
            } else {
                self.cacheSingleImage(list: array, finished: completion)
            }
            
        }
    }
    
    /// 缓存本次下载微博数据数组中的单张图像,缓存完单张图像,并且修改过配图视图的大小之后,再回调
    ///
    /// - Parameter list: 微博视图模型数组
    private func cacheSingleImage(list: [WBStatusViewModel], finished: @escaping (_ isSuccess: Bool, _ shouldRefresh: Bool) -> ()) {
        
        // 调度组
        let group = DispatchGroup()
        
        /// 记录数据长度
        var length = 0
        
        // 遍历数组,查找有单张图像的微博进行图片缓存
        for model in list {
            // 1.判断图像数量
            if model.picURLs?.count != 1 {
                continue
            } else {
                // 2.获取图像模型, 这里模型中有且只有一张
                guard let picURLStr = model.picURLs?.first?.thumbnail_pic, let url = URL(string: picURLStr) else {
                    return
                }
                
                // 3.下载图像,downloadImage是sdwebimage的核心方法,图像下载完成后,会自动保存的在沙盒,文件路径是url的md5
                // 如果沙盒已经存在相同的图像,不会重复下载,都会加载本地沙盒的图像,不会发起网络请求
                // 如果要缓存的图像累计很大,要找后台找接口
                
                // 入组
                group.enter()
                
                _ = SDWebImageManager.shared().imageDownloader?.downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _) in
                    
                    // 将图像转换成二进制数据
                    if let image = image {
                        let data = UIImagePNGRepresentation(image)
                        length += data?.count ?? 0
                        
                        // 图像缓存成功,更新配图视图的大小
                        model.updateSingleImageSize(image: image)
                    }
                    
                    // 出组
                    group.leave()
                })
            }
        }
        
        // 监听调度组情况
        group.notify(queue: DispatchQueue.main) {
            print("图像缓存完成,长度为\(length / 1024)K")
            // 完成单张缓存之后再回调
            finished(true, true)
        }
    }
}
